package ro.leje.jira.client;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;

import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.MediaType;

import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;

import ro.leje.jira.model.Issue;

import com.atlassian.jira.rest.client.api.JiraRestClient;
import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
import com.atlassian.jira.rest.client.api.RestClientException;
import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.Base64;

public class JiraClient {

	private static final String JIRA_SERVER = "http://yourdomain.ro";
	
	private static final String REST_PATH = "/rest/api/latest/";
	
	private static final String USERNAME = "user";
	
	private static final String PASSWORD = "secret";
	
	private static final int SUCCESS = 200;
	
	private final JiraRestClientFactory jiraRestClientFactory;

    private final JiraRestClient jiraRestClient;
	
	public JiraClient() {
		jiraRestClientFactory = new AsynchronousJiraRestClientFactory();
        try {
            jiraRestClient = jiraRestClientFactory.createWithBasicHttpAuthentication(new URL(JIRA_SERVER).toURI(), USERNAME, PASSWORD);
        }
        catch (MalformedURLException | URISyntaxException e) {
            throw new IllegalStateException();
        }
	}
	
	private ClientResponse rest(String query, String httpMethod, String jsonBody) {
		String auth = new String(Base64.encode(USERNAME + ":" + PASSWORD));
		Client client = Client.create();
		WebResource webResource = client.resource(JIRA_SERVER + REST_PATH + query);
		Builder builder = webResource.header("Authorization", "Basic " + auth)
				.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
		ClientResponse clientResponse = null;
		switch (httpMethod) {
			case HttpMethod.GET:
				clientResponse = builder.get(ClientResponse.class);
				break;
			case HttpMethod.POST:
				clientResponse = builder.post(ClientResponse.class, jsonBody);
				break;
			case HttpMethod.PUT:
				clientResponse = builder.put(ClientResponse.class);
				break;
			case HttpMethod.DELETE:
				clientResponse = builder.delete(ClientResponse.class);
		}
		return clientResponse;
	}
	
	private <T> T deserialize(String json, Class<T> clazz) {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.getDeserializationConfig().disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES);
        try {
            T object = objectMapper.readValue(json, clazz);
            if (object != null) {
                return object;
            }
            else {
                throw new IllegalStateException();
            }
        }
        catch (IOException e) {
        	throw new IllegalStateException();
        }
    }
	
	public Issue getIssueByKeyUsingJersey(String issueKey) {
		ClientResponse response = this.rest("issue/" + issueKey, HttpMethod.GET, null);
		if (response != null && response.getStatus() == SUCCESS) {
			String json = response.getEntity(String.class);
			return this.deserialize(json, Issue.class);
		}
		return null;
	}

	public com.atlassian.jira.rest.client.api.domain.Issue getIssueByKeyUsingJRJC(String issueKey) {
        try {
            return jiraRestClient.getIssueClient().getIssue(issueKey).claim();
        }
        catch (RestClientException e) {
        	throw new IllegalStateException();
        }
    }
}
